package com.db.httpclient;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class LoadTest {
	
	public static class Stats {
		private List<Double> stats;
		
		public Stats(List<Double> stats) {
			this.stats = stats;
		}
		
		public double getMinRequestTimeMillis() {
			return Collections.min(stats);
		}
		
		public double getMaxRequestTimeMillis() {
			return Collections.max(stats);
		}
		
		public double getAvgRequestTimeMillis() {
			double total = 0;
			for (double time : stats)
				total += time;
			return total / stats.size();
		}

		public void print() {
			System.out.println("Request stats");
			System.out.printf("min: %.4f%n", getMinRequestTimeMillis());
			System.out.printf("max: %.4f%n", getMaxRequestTimeMillis());
			System.out.printf("avg: %.4f%n", getAvgRequestTimeMillis());
		}

	}
	
	public static Stats runTest(int nClients, int nRequests) throws Exception {
		ExecutorService pool = Executors.newFixedThreadPool(nClients);
		List<Future<Long>> futureStats = new ArrayList<>(nRequests);
		
		for (int i = 0; i < nRequests; i++) {
			Future<Long> future = pool.submit(new Callable<Long>() {

				@Override
				public Long call() throws Exception {
					Client client = new Client("localhost");
					
					long time = System.nanoTime();
					client.get("/");
					time -= System.nanoTime();
					
					return -time;
				}
			});
			
			futureStats.add(future);
		}
		
		pool.shutdown();
		
		List<Double> stats = new ArrayList<>(nRequests);
		for (Future<Long> future : futureStats) {
			double timeMillis = 1.0 * future.get() / 1_000_000;
			stats.add(timeMillis);
		}
		
		return new Stats(stats);
	}
	
	public static void main(String[] args) throws Exception {
		if (args.length != 2) {
			System.out.println("Usage: java LoadTest <clients number> <requests number>");
			return;
		}

		int nClients = Integer.parseInt(args[0]);
		int nRequests = Integer.parseInt(args[1]);
		
		Stats stats = runTest(nClients, nRequests);
		stats.print();
	}
}
